package org.andao.core.support.context;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * 获取Spring Context的辅助类.
 * @author Seewo software - Marco.hu(huzhiguo@cvte.cn)
 *
 */
public class SpringContextHolder implements ApplicationContextAware {

	private static ApplicationContext applicationContext;
	
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {	
		SpringContextHolder.applicationContext = applicationContext;
	}

	/*
	 * 获取静态变量中的applicationContext
	 */
	public static ApplicationContext getApplicationContext() {
		checkApplicationContext();
		return applicationContext;
	}
	
	/*
	 * 根据bean id获取applicationContext中的Bean
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name) {
		checkApplicationContext();
		return (T) applicationContext.getBean(name);
	}
	
	/*
	 * 根据Bean class类型获取
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<T> clazz) {
		checkApplicationContext();
		return (T) applicationContext.getBeansOfType(clazz);
	}
	
	/**
	 * 获取bean ，若不存在则动态创建.
	 * @param beanName
	 * @param clazz
	 * @return
	 */
	public static Object getBeanIfNotCreate(String beanName,Class<?> clazz){
		checkApplicationContext();
		try{
			 applicationContext.getBean(beanName,clazz);
		}catch(NoSuchBeanDefinitionException e){
			register(beanName,clazz);	
		}				
		return applicationContext.getBean(beanName);
	}
	
	/**
	 * 动态注册bean.
	 * @param beanName
	 * @param clazz
	 */
	public static void register(String beanName,Class<?> clazz){
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
		 BeanDefinitionRegistry beanDefinitonRegistry = (BeanDefinitionRegistry) configurableApplicationContext.getBeanFactory();
		 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz); 		 
		 beanDefinitonRegistry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
	}
	/*
	 * 
	 * 监测是否注入这个类.
	 */
	private static void checkApplicationContext() {
		if (applicationContext == null)
			throw new IllegalStateException("未注入"+SpringContextHolder.class.getName());
	}
}
